package fr.sunnydale.android.geek.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import fr.sunnydale.android.geek.Dream;
import fr.sunnydale.android.geek.R;
import fr.sunnydale.android.geek.background.impl.Background;
import fr.sunnydale.android.geek.entity.factory.SpriteFactory;
import fr.sunnydale.android.geek.sprite.ISprite;
import fr.sunnydale.android.geek.sprite.impl.Sprite;
import fr.sunnydale.android.geek.thread.TimerThread;
import fr.sunnydale.android.geek.util.Direction;
import fr.sunnydale.android.geek.util.GUtils;
import fr.sunnydale.android.geek.util.Speed;
import fr.sunnydale.android.geek.util.TileCoord;

/**
 * Describes and runs the Game view as a tile based system.
 * @author doctor
 */
public class GameView extends SurfaceView implements SurfaceHolder.Callback {

    /**
     * The {@link GameThread} running the actual game.
     */
    private GameThread mGameThread;
    /**
     * The {@link TimerThread} that gives constant framerate to the game.
     */
    private TimerThread mClock;
    private ISprite[][] grid = new Sprite[8][6];

    /**
     * This subclass draws the screen.
     * @author doctor
     */
    class GameThread extends Thread {

        /**
         * The {@link SurfaceHolder}
         */
        private SurfaceHolder mSurfaceHolder;
        /**
         * The {@link Context}
         */
        private Context mContext;
        /**
         * The message {@link Handler}.
         */
        private Handler mHandler;
        /**
         * The running flag
         */
        private boolean mRun;

        /**
         * Constructor.
         * @param surfaceHolder
         *            The {@link SurfaceHolder}
         * @param context
         *            The running {@link Context}
         * @param handler
         *            A message {@link Handler}
         */
        public GameThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {
            mSurfaceHolder = surfaceHolder;
            mHandler = handler;
            mContext = context;
        }

        /**
         * Starts the {@link Thread}.
         */
        public void doStart() {
            synchronized (mSurfaceHolder) {
            }
        }

        /**
         * What is actually done in the thread.
         */
        @Override
        public void run() {
            while (mRun) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas();
                    synchronized (mSurfaceHolder) {
                        doDraw(c);
                    }
                } finally {
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

        /**
         * Drawing operation.
         * @param c
         */
        private void doDraw(Canvas c) {
            Background.mInstance.draw(c, mClock);
            // lonelySprite.draw(c, mClock);
            for (int i = 0; i < grid.length; i++) {
                ISprite[] row = grid[i];
                for (int j = 0; j < row.length; j++) {
                    ISprite sprite = row[j];
                    if (sprite != null)
                        sprite.draw(c, mClock);
                }
            }
            c.save();
        }
    }

    public GameView(Context context, AttributeSet aSet) {
        super(context, aSet);
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        mGameThread = new GameThread(holder, context, new Handler() {

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        });
        mClock = Dream.mTimerThread;
        setFocusable(true);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Background.mInstance.init(
                Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.testsky)), Speed.LIGHTNING,
                Direction.LEFT2RIGHT);
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                grid[i][j] = SpriteFactory.getSprite(getResources(), R.id.Terra);
                grid[i][j].setXY(i, j);
            }
        }
        mGameThread.mRun = true;
        mGameThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mGameThread.mRun = false;
        mGameThread.stop();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        TileCoord coord = GUtils.getTileFromRaw(event.getX(), event.getY());
        grid[coord.x][coord.y].touchAction();
        return super.onTouchEvent(event);
    }
}
